package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.constant.BusinessInnerMsgTemplate;
import com.eastfair.core.base.R;
import com.eastfair.core.base.entity.SuperEntity;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ExcelUtils;
import com.eastfair.home.api.ReportServiceAuditFeign;
import com.eastfair.home.dto.ReportServiceAuditDTO;
import com.eastfair.home.enumeration.ReportSpaceAuditServiceAuditStatusEnum;
import com.eastfair.messagecenter.util.SendMsgUtil;
import com.eastfair.projectcore.enumeration.DataIsolationSystemSceneEnum;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venueservice.dao.ServiceBookingMapper;
import com.eastfair.venueservice.dto.*;
import com.eastfair.venueservice.entity.*;
import com.eastfair.venueservice.enumeration.*;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ReportVenueSpaceNumVO;
import com.eastfair.venueservice.vo.ServiceBookingSimpleVO;
import com.eastfair.venueservice.vo.ServiceBookingStatisticsVO;
import com.eastfair.venueservice.vo.ServiceBookingVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.eastfair.venueservice.consts.CommonConstants.COMMON_IGNORE_PROPERTIES;

/**
* <p>
    * 业务实现类
    * 服务预订项
    * </p>
*
* @author linan
* @date 2022-08-05
*/
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceBookingServiceImpl extends SuperServiceImpl<ServiceBookingMapper, ServiceBooking> implements ServiceBookingService {

    public static final BigDecimal DISCOUNT = BigDecimal.valueOf(100);
    @Resource
    private ServiceItemService serviceItemService;
    @Resource
    private ReportServiceAuditFeign reportServiceAuditFeign;
    @Resource
    private ServiceInventoryService serviceInventoryService;
    @Resource
    private ServiceInventoryInFlowService serviceInventoryInFlowService;
    @Resource
    private ServiceInventoryOutFlowService serviceInventoryOutFlowService;
    @Resource
    private ServiceCategoryService serviceCategoryService;
    @Resource
    private HomeServiceOrderService homeServiceOrderService;
    @Resource
    private ServiceOrderService serviceOrderService;
    @Resource
    private ServiceItemDetailService serviceItemDetailService;
    @Resource
    private ServiceProviderService serviceProviderService;
    @Resource
    private ExhibitionManageService exhibitionManageService;
    @Resource
    private DepositWarningService depositWarningService;

    @Resource
    private ServiceOrderOperateLogService serviceOrderOperateLogService;

    @Resource
    private ExhibitionSettlementService exhibitionSettlementService;

    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Resource
    private SendMsgUtil sendMsgUtil;

    private static final String REPORT_VENUE_SPACE_NUMBER_PREFIX = "RSV";

    private static final String REPORT_VENUE_SPACE_NUMBER_FIELD = "report_venue_space_number";

    private static final int REPORT_VENUE_SPACE_NUMBER_LENGTH = 8;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
    */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceBooking> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    public R<Boolean> handlerSave(ServiceBooking model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTenantId(ContextUtil.getTenantId());
        model.setWorkOrderStatus(ServiceBookingWorkOrderStatusEnum.NOT_DISPATCH);
        if(Objects.isNull(model.getReportSpaceStatus())){
            model.setReportSpaceStatus(ServiceBookingReportSpaceStatusEnum.NOT_REPORTED);
        }
        if (model.getReportCheckStatus() == null) {
            model.setReportCheckStatus(ServiceBookingReportCheckStatusEnum.NOT_CHECK);
        }
        return R.successDef();
    }

    @Override
    public List<ServiceBookingVO> listServiceBookingBySiteName(ServiceBookingDTO serviceBookingDTO) {
        log.info("listServiceBookingBySiteName - 查询展位上预定的服务列表, serviceBookingDTO={}", serviceBookingDTO);
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("sb.is_deleted", BusinessConstant.DELETE_NO)
                .eq("sb.is_enabled", BusinessConstant.ENABLE_YES)
                .eq(serviceBookingDTO.getBusinessId() != null, "sb.business_id", serviceBookingDTO.getBusinessId())
                .eq(serviceBookingDTO.getExhibitionManageId() != null, "sb.exhibition_manage_id", serviceBookingDTO.getExhibitionManageId())
                .eq(StrUtil.isNotBlank(serviceBookingDTO.getSiteName()), "sb.site_name", serviceBookingDTO.getSiteName())
                .eq(StrUtil.isNotBlank(serviceBookingDTO.getSpaceName()), "sb.space_name", serviceBookingDTO.getSpaceName())
        ;
        return baseMapper.listServiceBookingBySiteName(queryWrapper);
    }


    @Override
    public void updateByItem(ServiceItemDTO serviceItemDTO) {
        List<ServiceItemDetailDTO> serviceItemDetailList = serviceItemDTO.getServiceItemDetailList();
        List<ReportServiceAuditDTO> reportServiceAuditDTOS = new ArrayList<>();
        for (ServiceItemDetailDTO serviceItemDetailDTO : serviceItemDetailList) {
            LambdaUpdateWrapper<ServiceBooking> set = new UpdateWrapper<ServiceBooking>().lambda()
                    .eq(ServiceBooking::getServiceItemId, serviceItemDTO.getId())
                    .eq(ServiceBooking::getServiceCategoryId, serviceItemDetailDTO.getServiceCategoryId())
                    .eq(ServiceBooking::getServiceSpecsId, serviceItemDetailDTO.getServiceSpecsId())
                    // 只修改未生成订单的
                    .eq(ServiceBooking::getGenerateOrder, BusinessConstant.NO)
                    .eq(ServiceBooking::getIsDeleted, BusinessConstant.NO)
                    // 服务名称
                    .set(ServiceBooking::getServiceName, serviceItemDTO.getServiceName())
                    // 服务图片
                    .set(ServiceBooking::getPicUrl, serviceItemDTO.getPicUrl())
                    // 计量单位
                    .set(ServiceBooking::getCalUnit, serviceItemDTO.getCalUnit())
                    // 服务单价
                    .set(ServiceBooking::getUnitPrice, serviceItemDetailDTO.getUnitPrice())
                    // 附加费
                    .set(ServiceBooking::getSurcharge, serviceItemDetailDTO.getSurcharge());
            update(set);
            ReportServiceAuditDTO reportServiceAuditDTO = new ReportServiceAuditDTO();
            reportServiceAuditDTO.setServiceItemId(serviceItemDTO.getId());
            reportServiceAuditDTO.setServiceCategoryId(serviceItemDetailDTO.getServiceCategoryId());
            reportServiceAuditDTO.setServiceSpecsId(serviceItemDetailDTO.getServiceSpecsId());
            reportServiceAuditDTO.setGenerateOrder(BusinessConstant.NO);
            reportServiceAuditDTO.setIsDeleted(BusinessConstant.NO);
            reportServiceAuditDTO.setServiceName(serviceItemDTO.getServiceName());
            reportServiceAuditDTO.setPicUrl(serviceItemDTO.getPicUrl());
            reportServiceAuditDTO.setCalUnit(serviceItemDTO.getCalUnit());
            reportServiceAuditDTO.setUnitPrice(serviceItemDetailDTO.getUnitPrice());
            reportServiceAuditDTO.setSurcharge(serviceItemDetailDTO.getSurcharge());
            reportServiceAuditDTOS.add(reportServiceAuditDTO);
        }
        // 更新未生成订单的报馆服务审核记录
        R<Boolean> booleanR = reportServiceAuditFeign.updateByItem(reportServiceAuditDTOS);
        if(!booleanR.getIsSuccess()){
            throw BizException.wrap(booleanR.getCode(),booleanR.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addServiceBooking(List<ServiceBookingDTO> serviceBookingDTOS) {
        for (ServiceBookingDTO serviceBookingDTO : serviceBookingDTOS) {
            ServiceBooking serviceBooking = BeanUtil.copyProperties(serviceBookingDTO, ServiceBooking.class, COMMON_IGNORE_PROPERTIES);
            serviceBooking.setReportSpaceStatus(ServiceBookingReportSpaceStatusEnum.NOT_REPORTED);
            // 先删除
            update(new UpdateWrapper<ServiceBooking>().lambda()
                    .eq(ServiceBooking::getIsDeleted,BusinessConstant.NO)
                    .eq(ServiceBooking::getServiceItemId,serviceBooking.getServiceItemId())
                    .eq(ServiceBooking::getServiceCategoryId,serviceBooking.getServiceCategoryId())
                    .eq(ServiceBooking::getServiceSpecsId,serviceBooking.getServiceSpecsId())
                    .eq(ServiceBooking::getReportSpaceId,serviceBooking.getReportSpaceId())
                    .set(ServiceBooking::getIsDeleted,BusinessConstant.YES));
            if (serviceBookingDTO.getBookingNum() != 0) {
                // 校验库存和最小预定量
                checkServiceBooking(serviceBookingDTO);
            }
            // 再根据预定数量是否大于0，进行插入
            if (Objects.nonNull(serviceBooking.getBookingNum()) && serviceBooking.getBookingNum() > 0) {
                // 处理统计项
                dealSubTotal(serviceBooking);
                save(serviceBooking);
            }
        }
        return true;
    }

    private void dealSubTotal(ServiceBooking serviceBooking) {
        BigDecimal discount = (Objects.nonNull(serviceBooking.getDiscount()) ? serviceBooking.getDiscount() : new BigDecimal("100"))
                .divide(new BigDecimal("100"), 4, RoundingMode.DOWN)
                .setScale(4, RoundingMode.DOWN);
        BigDecimal unitPrice = Objects.nonNull(serviceBooking.getUnitPrice())? serviceBooking.getUnitPrice():BigDecimal.ZERO;
        long bookingNum = Objects.nonNull( serviceBooking.getBookingNum())? serviceBooking.getBookingNum():0L;
        BigDecimal surcharge = Objects.nonNull(serviceBooking.getSurcharge()) ? serviceBooking.getSurcharge() : BigDecimal.ZERO;
        // 计算折后单价 向下取整
        BigDecimal unitPriceAfterDiscount = unitPrice
                .multiply(discount)
                .setScale(2, RoundingMode.DOWN);
        serviceBooking.setUnitPriceAfterDiscount(unitPriceAfterDiscount);
        // 服务总金额
        BigDecimal subtotalServicePrice = unitPriceAfterDiscount
                .multiply(BigDecimal.valueOf(bookingNum))
                .setScale(2, RoundingMode.DOWN);
        serviceBooking.setSubtotalServicePrice(subtotalServicePrice);
        // 附加费总金额
        BigDecimal subtotalSurchargePrice = BigDecimal
                .valueOf(bookingNum)
                .multiply(Objects.nonNull(surcharge) ? surcharge : BigDecimal.ZERO)
                .setScale(2, RoundingMode.DOWN);
        serviceBooking.setSubtotalSurchargePrice(subtotalSurchargePrice);
        // 总金额
        serviceBooking.setSubtotalPrice(subtotalServicePrice);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addServiceBookingOfOrder(List<ServiceBookingDTO> serviceBookingDTOS) {
        // 查询之前的服务
        List<ServiceBooking> oldServiceBookingList = queryByOrderNumber(serviceBookingDTOS.get(0).getOrderNumber());
        LocalDateTime now = LocalDateTime.now();
        // 先删除
        update(new UpdateWrapper<ServiceBooking>().lambda()
                .eq(ServiceBooking::getIsDeleted,BusinessConstant.NO)
                .eq(ServiceBooking::getOrderNumber,serviceBookingDTOS.get(0).getOrderNumber())
                .set(ServiceBooking::getIsDeleted,BusinessConstant.YES));
        for (ServiceBookingDTO serviceBookingDTO : serviceBookingDTOS) {
            ServiceBooking serviceBooking = BeanUtil.copyProperties(serviceBookingDTO, ServiceBooking.class, COMMON_IGNORE_PROPERTIES);
            if (serviceBookingDTO.getBookingNum() != 0) {
                // 校验库存和最小预定量
                checkServiceBooking(serviceBookingDTO);
            }
            // 再根据预定数量是否大于0，进行插入
            if (Objects.nonNull(serviceBooking.getBookingNum()) && serviceBooking.getBookingNum() > 0) {
                serviceBooking.setPayState(ServiceBookingPayStateEnum.UN_PAY);
                serviceBooking.setOrderStatus(ServiceBookingOrderStatusEnum.NOT_SUBMIT);
                serviceBooking.setBookingTime(now);
                dealSubTotal(serviceBooking);
                save(serviceBooking);
            }
        }
        // 记录操作日志
        if (StrUtil.isNotBlank(serviceBookingDTOS.get(0).getOrderNumber())) {
            serviceOrderOperateLogService.asyncLogAddOrderService(serviceBookingDTOS, oldServiceBookingList);
            serviceOrderOperateLogService.asyncLogUpdateOrderService(serviceBookingDTOS, oldServiceBookingList);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addServiceBookingAfterReport(List<ServiceBookingDTO> serviceBookingDTOS) {
        for (ServiceBookingDTO serviceBookingDTO : serviceBookingDTOS) {
            ServiceBooking serviceBooking = BeanUtil.copyProperties(serviceBookingDTO, ServiceBooking.class, COMMON_IGNORE_PROPERTIES);
            if (serviceBookingDTO.getBookingNum() != 0) {
                // 校验库存和最小预定量
                checkServiceBooking(serviceBookingDTO);
            }
            // 再根据预定数量是否大于0，进行插入
            if (Objects.nonNull(serviceBooking.getBookingNum()) && serviceBooking.getBookingNum() > 0) {
                // 默认审核通过，直接推给主场
                serviceBooking.setAuditState(ServiceItemAuditStateEnum.APPROVED.getCode());
                serviceBooking.setReportSpaceStatus(ServiceBookingReportSpaceStatusEnum.NOT_REPORTED);
                serviceBooking.setWorkOrderStatus(ServiceBookingWorkOrderStatusEnum.NOT_DISPATCH);
                save(serviceBooking);
            }
        }
        return true;
    }

    @Override
    public Page<ServiceBookingVO> queryServiceBookingOfHome(PageParams<ServiceBookingQuery> serviceBookingQuery) {
        Page<ServiceBookingQuery> page = serviceBookingQuery.buildPage();
        ServiceBookingQuery model = serviceBookingQuery.getModel();
        QueryWrapper<ServiceBooking> wrapper = new QueryWrapper<>();
        wrapper.eq("a.is_deleted",BusinessConstant.NO)
                .eq("a.is_enabled", BusinessConstant.YES)
                .in("a.declaration_system", Arrays.asList( DataIsolationSystemSceneEnum.P_COMPOSITE_PRODUCER.getCode(),DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode()))
                .eq("d.source_provider", DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode())
                .eq("a.provider_system", DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode())
                .eq( StringUtils.isNotEmpty(model.getAuditState()),"a.audit_state", model.getAuditState())
                .eq(Objects.nonNull(model.getExhibitionManageId()),"a.exhibition_manage_id", model.getExhibitionManageId())
                .eq(StringUtils.isNotBlank(model.getSpaceCode()), "a.space_code", model.getSpaceCode())
                .eq(StringUtils.isNotBlank(model.getSpaceName()), "a.space_name", model.getSpaceName())
                .and( (Objects.nonNull(model.getReportVenueSpaceOrNot()) && model.getReportVenueSpaceOrNot() == 0)||StringUtils.isNotBlank(model.getReportVenueSpaceNumber()), wrapper2 -> wrapper2
                        .isNull(Objects.nonNull(model.getReportVenueSpaceOrNot()) && model.getReportVenueSpaceOrNot() == 0,"a.report_venue_space_number")
                        .or()
                        .eq( StringUtils.isNotBlank(model.getReportVenueSpaceNumber()), "a.report_venue_space_number",model.getReportVenueSpaceNumber()))
                .eq(Objects.nonNull(model.getPayState()), "a.pay_state", model.getPayState())
                .isNotNull(Objects.nonNull(model.getReportVenueSpaceOrNot()) && model.getReportVenueSpaceOrNot() == 1, "a.report_venue_space_number")
                .eq(Objects.nonNull(model.getReportSpaceStatus()), "a.report_space_status",model.getReportSpaceStatus())
                .notIn("a.order_status", Collections.singletonList(ServiceBookingOrderStatusEnum.CANCEL))
                .like(StringUtils.isNotBlank(model.getBusinessName()), "b.company_name", model.getBusinessName())
                .like(StringUtils.isNotBlank(model.getExhibitorName()), "c.company_name", model.getExhibitorName())
                .and(StringUtils.isNotBlank(model.getKeywords()),
                        e->e.like("a.site_name",model.getKeywords())
                                .or().like("d.service_name",model.getKeywords())
                                .or().like("b.company_name",model.getKeywords())
                                .or().like("a.order_number",model.getKeywords()))
                .orderByDesc("a.booking_time")
                .orderByDesc("a.create_time");
        Page<ServiceBookingVO> serviceBookingVOPage = baseMapper.queryServiceBookingOfHome(page, wrapper);
        return serviceBookingVOPage;
    }

    @Override
    public Page<ServiceBookingVO> queryReportSpaceService(PageParams<ServiceBookingQuery> serviceBookingQuery) {
        Page<ServiceBookingQuery> page = serviceBookingQuery.buildPage();
        ServiceBookingQuery model = serviceBookingQuery.getModel();
        QueryWrapper<ServiceBooking> wrapper = new QueryWrapper<>();
        wrapper.eq("a.report_space_status",ServiceBookingReportSpaceStatusEnum.REPORTED)
                .eq("a.is_deleted",BusinessConstant.NO)
                .eq("a.is_enabled", BusinessConstant.YES)
                .in("d.source_provider", Arrays.asList(DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode(),DataIsolationSystemSceneEnum.P_COMPOSITE_MATING.getCode()) )
                .eq("a.provider_system", DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode())
                .eq("a.exhibition_manage_id", model.getExhibitionManageId())
                .eq(Objects.nonNull(model.getServiceCategoryId()),"a.service_category_id", model.getServiceCategoryId())
                .eq(StringUtils.isNotBlank(model.getSpaceCode()), "a.space_code", model.getSpaceCode())
                .eq(StringUtils.isNotBlank(model.getSpaceName()), "a.space_name", model.getSpaceName())
                .like(StringUtils.isNotBlank(model.getSiteName()), "a.site_name", model.getSiteName())
                .and(StringUtils.isNotBlank(model.getKeywords()),
                        e->e.like("d.service_name",model.getKeywords())
                                .or().like("b.company_name",model.getKeywords())
                                .or().like("a.exhibitor_name",model.getKeywords()))
//                                .or().like("a.order_number",model.getKeywords()))
                .orderByDesc("a.report_space_time")
                .orderByDesc("a.create_time");
        Page<ServiceBookingVO> serviceBookingVOPage = baseMapper.queryServiceBookingOfHome(page, wrapper);
        return serviceBookingVOPage;
    }

    @Override
    public Page<ServiceBookingVO> queryServiceBookingManage(PageParams<ServiceBookingQuery> serviceBookingQuery) {
        ServiceBookingQuery model = serviceBookingQuery.getModel();
        Page<ServiceItem> serviceItemPage = serviceBookingQuery.buildPage();

        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("a.is_deleted",BusinessConstant.NO)
                .eq(Objects.nonNull(model.getBusinessId()),"a.business_id",model.getBusinessId())
                .eq(Objects.nonNull(model.getExhibitionManageId()),"a.exhibition_manage_id",model.getExhibitionManageId())
                .eq(Objects.nonNull(model.getAuditState()),"a.audit_state",model.getAuditState())
                .eq(Objects.nonNull(model.getPayState()),"a.pay_state",model.getPayState())
                .eq(Objects.nonNull(model.getGenerateOrder()),"a.generate_order",model.getGenerateOrder())
                .orderByDesc("a.create_time");
        return  baseMapper.queryServiceBookingManage(serviceItemPage, queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitServiceBookingToVenue(List<ServiceBookingDTO> serviceBookingDTO) {
        LocalDateTime now = LocalDateTime.now();
        Long homeId = null;
        Long exhibitionManageId = CollectionUtils.isNotEmpty(serviceBookingDTO)? getById(serviceBookingDTO.get(0)).getExhibitionManageId():null;
        // 校验场馆结算状态
        if(Objects.nonNull(exhibitionManageId)){
            ExhibitionSettlementDTO exhibitionSettlementDTO = new ExhibitionSettlementDTO();
            exhibitionSettlementDTO.setExhibitionManageId(exhibitionManageId);
            exhibitionSettlementDTO.setCompanyType(ExhibitionSettlementCompanyTypeEnum.HOME_SERVICE_PROVIDER);
            exhibitionSettlementService.checkSettleState(exhibitionSettlementDTO);
        }
        for (ServiceBookingDTO bookingDTO : serviceBookingDTO) {
            // 查询场馆给主场定的服务价格
            ServiceBooking booking = getById(bookingDTO.getId());
            homeId = bookingDTO.getHomeId();
            exhibitionManageId = booking.getExhibitionManageId();
            ExhibitionManage exhibitionManage = exhibitionManageService.getById(booking.getExhibitionManageId());
            Long serviceCategoryId = booking.getServiceCategoryId();
            Long serviceSpecsId = booking.getServiceSpecsId();
            ServiceItem serviceItem = serviceItemService.getById(booking.getServiceItemId());
            // 处理库存和服务预定
            dealServiceBookingAndInventory(now, bookingDTO, booking, exhibitionManage, serviceCategoryId, serviceSpecsId, serviceItem);
            baseMapper.updateById(ServiceBooking.builder()
                    .id(bookingDTO.getId())
//                    .reportVenueSpaceNumber(bookingDTO.getReportVenueSpaceNumber())
                    .homeId(bookingDTO.getHomeId())
                    .reportSpaceTime(now)
                    .reportSpaceStatus(ServiceBookingReportSpaceStatusEnum.REPORTED).build());
        }
        // 更新订单搭建商订单服务报馆状态
        List<ServiceOrder> orderNumbers = baseMapper.selectOrderNumbers(serviceBookingDTO.stream().map(ServiceBookingDTO::getId).collect(Collectors.toList()));
        for (ServiceOrder orderNumber : orderNumbers) {
            homeServiceOrderService.updateServiceReportVenueStatus(orderNumber);
        }
        //
        // 异步处理押金预警
        if(Objects.nonNull(homeId) && Objects.nonNull(exhibitionManageId)){
            depositWarningService.warning(homeId,exhibitionManageId);
            serviceItemService.waring(homeId,exhibitionManageId);
        }
        // 发送一键报馆站内信消息
        asyncSendVenueReportInnerMsg(exhibitionManageId, homeId);
        return true;
    }

    /**
     * 处理库存和服务预定
     * @param now now
     * @param bookingDTO bookingDTO
     * @param booking booking
     * @param exhibitionManage exhibitionManage
     * @param serviceCategoryId serviceCategoryId
     * @param serviceSpecsId serviceSpecsId
     * @param serviceItem serviceItem
     */
    private void dealServiceBookingAndInventory(LocalDateTime now, ServiceBookingDTO bookingDTO, ServiceBooking booking, ExhibitionManage exhibitionManage, Long serviceCategoryId, Long serviceSpecsId, ServiceItem serviceItem) {
        if(Objects.nonNull(serviceItem) && Objects.nonNull(serviceItem.getSourceId())){
            ServiceItem venueServiceItem = serviceItemService.getById(serviceItem.getSourceId());
            if(Objects.nonNull(venueServiceItem)){
                // 场馆的服务明细
                ServiceItemDetail serviceItemDetail = getServiceItemDetailServiceOne(venueServiceItem, serviceCategoryId, serviceSpecsId);
                LocalDateTime preDiscountStartTime = exhibitionManage.getPreDiscountStartTime();
                LocalDateTime preDiscountEndTime = exhibitionManage.getPreDiscountEndTime();
                LocalDateTime onDiscountStartTime = exhibitionManage.getOnDiscountStartTime();
                LocalDateTime onDiscountEndTime = exhibitionManage.getOnDiscountEndTime();
                // 折扣
                BigDecimal discount = BigDecimal.valueOf(100);
                discount = dealDiscount(preDiscountStartTime, preDiscountEndTime, now, discount, serviceItemDetail, onDiscountStartTime, onDiscountEndTime);
                // 准备插入新的数据
                ServiceBooking newBooking = insertNewBooking(now, bookingDTO, booking, venueServiceItem, serviceItemDetail, discount);
                // 扣场馆库存
                // 保存出库记录
                ServiceInventory serviceInventory = serviceInventoryService.getOne(new QueryWrapper<ServiceInventory>().lambda()
                        .eq(ServiceInventory::getIsDeleted, BusinessConstant.NO)
                        .eq(ServiceInventory::getServiceItemId, newBooking.getServiceItemId())
                        .eq(ServiceInventory::getServiceCategoryId, newBooking.getServiceCategoryId())
                        .eq(ServiceInventory::getServiceSpecsId, newBooking.getServiceSpecsId()));
                if(Objects.nonNull(serviceInventory)){
                    ServiceInventoryOutFlowDTO serviceInventoryOutFlowDTO = new ServiceInventoryOutFlowDTO();
                    serviceInventoryOutFlowDTO.setInventoryCode(serviceInventory.getInventoryCode());
                    serviceInventoryOutFlowDTO.setOutNum(BigDecimal.valueOf(newBooking.getBookingNum()));
                    serviceInventoryOutFlowDTO.setOutStockType(ServiceInventoryOutFlowOutStockTypeEnum.ORDER);
                    serviceInventoryOutFlowDTO.setExhibitionManageId(newBooking.getExhibitionManageId());
                    serviceInventoryOutFlowService.saveOutFlow(serviceInventoryOutFlowDTO);
                }
            }
        }
    }

    /**
     * 准备插入新的数据
     * @param now now
     * @param bookingDTO bookingDTO
     * @param booking booking
     * @param venueServiceItem venueServiceItem
     * @param serviceItemDetail serviceItemDetail
     * @param discount discount
     * @return ServiceBooking
     */
    private ServiceBooking insertNewBooking(LocalDateTime now, ServiceBookingDTO bookingDTO, ServiceBooking booking, ServiceItem venueServiceItem, ServiceItemDetail serviceItemDetail, BigDecimal discount) {
        ServiceBooking newBooking = BeanUtil.copyProperties(booking, ServiceBooking.class, COMMON_IGNORE_PROPERTIES);
        newBooking.setServiceItemId(venueServiceItem.getId());
        newBooking.setDiscount(discount);
        newBooking.setUnitPrice(serviceItemDetail.getUnitPrice());
        newBooking.setSurcharge(serviceItemDetail.getSurcharge());
        newBooking.setBookingTime(now);
        newBooking.setReportSpaceId(null);
        newBooking.setDeclarationSystem(DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode());
        newBooking.setProviderSystem(DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode());
        newBooking.setOrderNumber(booking.getId().toString());
        newBooking.setOrderStatus(ServiceBookingOrderStatusEnum.SUBMIT);
        newBooking.setReportVenueSpaceNumber(bookingDTO.getReportVenueSpaceNumber());
        newBooking.setReportSpaceTime(now);
        newBooking.setSettlementNo(null);
        newBooking.setBuilderSettlementNo(null);
        newBooking.setHomeId(bookingDTO.getHomeId());
        newBooking.setReportSpaceStatus(ServiceBookingReportSpaceStatusEnum.REPORTED);
        dealSubTotal(newBooking);
        checkServiceBooking(BeanUtil.copyProperties(newBooking,ServiceBookingDTO.class));
        save(newBooking);
        return newBooking;
    }

    @Override
    public Boolean submitServiceBookingToVenueOfImport(List<ServiceBookingDTO> serviceBookingDTO) {
        LocalDateTime now = LocalDateTime.now();
        Long homeId = null;
        Long exhibitionManageId = CollectionUtils.isNotEmpty(serviceBookingDTO)? serviceBookingDTO.get(0).getExhibitionManageId():null;
        // 校验场馆结算状态
        if(Objects.nonNull(exhibitionManageId)){
            ExhibitionSettlementDTO exhibitionSettlementDTO = new ExhibitionSettlementDTO();
            exhibitionSettlementDTO.setExhibitionManageId(exhibitionManageId);
            exhibitionSettlementDTO.setCompanyType(ExhibitionSettlementCompanyTypeEnum.HOME_SERVICE_PROVIDER);
            exhibitionSettlementService.checkSettleState(exhibitionSettlementDTO);
        }
        // 生成一键报馆编码
        String reportVenueSpaceNumber = CreatCode.creatCode(baseMapper, REPORT_VENUE_SPACE_NUMBER_FIELD,
                REPORT_VENUE_SPACE_NUMBER_LENGTH, REPORT_VENUE_SPACE_NUMBER_PREFIX);
        for (ServiceBookingDTO bookingDTO : serviceBookingDTO) {
            // 查询场馆给主场定的服务价格
            homeId = bookingDTO.getHomeId();
            exhibitionManageId = bookingDTO.getExhibitionManageId();
            ExhibitionManage exhibitionManage = exhibitionManageService.getById(bookingDTO.getExhibitionManageId());
            Long serviceCategoryId = bookingDTO.getServiceCategoryId();
            Long serviceSpecsId = bookingDTO.getServiceSpecsId();
            ServiceItem serviceItem = serviceItemService.getById(bookingDTO.getServiceItemId());
            if(Objects.nonNull(serviceItem) && Objects.nonNull(serviceItem.getSourceId())){
                ServiceItem venueServiceItem = serviceItemService.getById(serviceItem.getSourceId());
                if(Objects.nonNull(venueServiceItem)){
                    // 场馆的服务明细
                    ServiceItemDetail serviceItemDetail = getServiceItemDetailServiceOne(venueServiceItem, serviceCategoryId, serviceSpecsId);
                    LocalDateTime preDiscountStartTime = exhibitionManage.getPreDiscountStartTime();
                    LocalDateTime preDiscountEndTime = exhibitionManage.getPreDiscountEndTime();
                    LocalDateTime onDiscountStartTime = exhibitionManage.getOnDiscountStartTime();
                    LocalDateTime onDiscountEndTime = exhibitionManage.getOnDiscountEndTime();
                    // 折扣
                    BigDecimal discount = DISCOUNT;
                    discount = dealDiscount(preDiscountStartTime, preDiscountEndTime, now, discount, serviceItemDetail, onDiscountStartTime, onDiscountEndTime);
                    // 准备插入新的数据
                    ServiceBooking newBooking = BeanUtil.copyProperties(bookingDTO, ServiceBooking.class, COMMON_IGNORE_PROPERTIES);
                    packageEntity(now, reportVenueSpaceNumber, bookingDTO, serviceItem, venueServiceItem, serviceItemDetail, discount, newBooking);
                    save(newBooking);
                }
            }
        }
        // 异步处理押金预警
        if(Objects.nonNull(homeId) && Objects.nonNull(exhibitionManageId)){
            depositWarningService.warning(homeId,exhibitionManageId);
            serviceItemService.waring(homeId,exhibitionManageId);
        }
        // 发送一键报馆站内信消息
        asyncSendVenueReportInnerMsg(exhibitionManageId, homeId);
        return true;
    }

    private BigDecimal dealDiscount(LocalDateTime preDiscountStartTime, LocalDateTime preDiscountEndTime, LocalDateTime now, BigDecimal discount, ServiceItemDetail serviceItemDetail, LocalDateTime onDiscountStartTime, LocalDateTime onDiscountEndTime) {
        if (Objects.nonNull(preDiscountStartTime) && Objects.nonNull(preDiscountEndTime) && now.compareTo(preDiscountStartTime) >= 0 && now.compareTo(preDiscountEndTime) <= 0) {
            discount = serviceItemDetail.getPreExhibitionDiscount();
        } else if (Objects.nonNull(onDiscountStartTime) && Objects.nonNull(onDiscountEndTime) && now.compareTo(onDiscountStartTime) >= 0 && now.compareTo(onDiscountEndTime) <= 0) {
            discount = serviceItemDetail.getOnSiteDiscount();
        }
        return discount;
    }

    private ServiceItemDetail getServiceItemDetailServiceOne(ServiceItem venueServiceItem, Long serviceCategoryId, Long serviceSpecsId) {
        return serviceItemDetailService.getOne(new QueryWrapper<ServiceItemDetail>().lambda()
                .eq(ServiceItemDetail::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceItemDetail::getServiceItemId, venueServiceItem.getId())
                .eq(ServiceItemDetail::getServiceCategoryId, serviceCategoryId)
                .eq(ServiceItemDetail::getServiceSpecsId, serviceSpecsId));
    }

    private void packageEntity(LocalDateTime now, String reportVenueSpaceNumber, ServiceBookingDTO bookingDTO, ServiceItem serviceItem, ServiceItem venueServiceItem, ServiceItemDetail serviceItemDetail, BigDecimal discount, ServiceBooking newBooking) {
        newBooking.setServiceItemId(venueServiceItem.getId());
        newBooking.setDiscount(discount);
        newBooking.setUnitPrice(serviceItemDetail.getUnitPrice());
        newBooking.setSurcharge(serviceItemDetail.getSurcharge());
        newBooking.setBookingTime(now);
        newBooking.setReportSpaceId(null);
        newBooking.setDeclarationSystem(DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode());
        newBooking.setProviderSystem(DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode());
        newBooking.setOrderStatus(ServiceBookingOrderStatusEnum.SUBMIT);
        newBooking.setOrderNumber(bookingDTO.getReportVenueSpaceNumber());
        newBooking.setReportVenueSpaceNumber(bookingDTO.getReportVenueSpaceNumber());
        newBooking.setSettlementNo(null);
        newBooking.setBuilderSettlementNo(null);
        newBooking.setHomeId(bookingDTO.getHomeId());
        newBooking.setReportSpaceStatus(ServiceBookingReportSpaceStatusEnum.REPORTED);
        newBooking.setServiceName(serviceItem.getServiceName());
        newBooking.setPicUrl(serviceItem.getPicUrl());
        newBooking.setReportVenueSpaceNumber(reportVenueSpaceNumber);
        dealSubTotal(newBooking);
    }

    @Override
    public Map<String, Integer> queryBookingServiceNum(List<String> reportVenueSpaceNumbers) {
        Map<String, Integer> map = new HashMap<>();
        if(CollectionUtils.isNotEmpty(reportVenueSpaceNumbers)){
            List<Map<String, Object>> result =  baseMapper.queryBookingServiceNum(reportVenueSpaceNumbers);
            for (Map<String, Object> stringObjectMap : result) {
                map.put(stringObjectMap.get("report_venue_space_number").toString(),Integer.parseInt(stringObjectMap.get("num").toString()));
            }
        }
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveServiceBooking(List<ServiceBookingDTO> serviceBookingDTO) {
        LocalDateTime now = LocalDateTime.now();
        for (ServiceBookingDTO bookingDTO : serviceBookingDTO) {
            checkServiceBooking(bookingDTO);
            update(new UpdateWrapper<ServiceBooking>().lambda()
                            .eq(SuperEntity::getId,bookingDTO.getId())
                            .set(ServiceBooking::getBookingNum,bookingDTO.getBookingNum())
                            .set(ServiceBooking::getDiscount,bookingDTO.getDiscount())
                            .set(ServiceBooking::getBookingTime,now));
        }
        return true;
    }

    /**
     * 校验服务预订项
     * @param bookingDTO bookingDTO
     */
    private void checkServiceBooking(ServiceBookingDTO bookingDTO) {
        ServiceItem serviceItem = serviceItemService.getById(bookingDTO.getServiceItemId());
        if (Objects.isNull(serviceItem) || BusinessConstant.YES == serviceItem.getIsDeleted() || !ServiceItemServiceStateEnum.ON_SHELVES.eq(serviceItem.getServiceState())) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICES_NOT_ON_SHELVES);
        }
        // 查询服务库存
        List<ServiceInventory> list = serviceInventoryService.list(new QueryWrapper<ServiceInventory>().lambda()
                .eq(ServiceInventory::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceInventory::getServiceItemId, bookingDTO.getServiceItemId())
                .eq(ServiceInventory::getServiceCategoryId, bookingDTO.getServiceCategoryId())
                .eq(ServiceInventory::getServiceSpecsId, bookingDTO.getServiceSpecsId()));
        if(CollectionUtils.isNotEmpty(list)){
            ServiceInventory serviceInventory = list.get(0);
            Long bookingNum = bookingDTO.getBookingNum();
            if (Objects.isNull(bookingNum) || bookingNum <= 0) {
                throw BizException.wrap(VenueServiceExceptionCode.BOOK_NUM_MUST_MORE_TRAN_ZERO);
            }
            Long inventoryNum = serviceInventory.getInventoryNum().longValue();
            Long minBookNum = serviceItem.getMinAllocatedNum().longValue();
            // 预订量不允许小于最小预定量限制
            if (bookingNum < minBookNum) {
                throw BizException.wrap(VenueServiceExceptionCode.NUM_CANT_LESS_TRAN_MIN);
            }
            // 服务预定量不允许大于当前库存量
            if (bookingNum > inventoryNum) {
                throw BizException.wrap(VenueServiceExceptionCode.NUM_CANT_MORE_TRAN_INVENTORY);
            }
        }else {
            throw BizException.wrap(VenueServiceExceptionCode.NUM_CANT_MORE_TRAN_INVENTORY);
        }
    }

    @Override
    public List<ServiceBookingVO> queryServiceBookingList(ServiceBookingQuery serviceBookingQuery) {
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("a.is_deleted",BusinessConstant.NO)
                .eq("a.is_enabled",BusinessConstant.YES)
                .eq(Objects.nonNull(serviceBookingQuery.getReportSpaceId()),"a.report_space_id",serviceBookingQuery.getReportSpaceId())
                .eq(Objects.nonNull(serviceBookingQuery.getBusinessId()),"a.business_id",serviceBookingQuery.getBusinessId())
                .orderByAsc("convert(a.service_name using gbk)")
        ;
        return baseMapper.queryServiceBookingList(queryWrapper);
    }

    @Override
    public List<ServiceBookingVO> queryServiceBookingListOfOrder(ServiceBookingQuery serviceBookingQuery) {
        // 结算单特殊处理
        if(serviceBookingQuery.getOrderNumber().startsWith("JS")){
            return exhibitionSettlementService.queryServiceBookingListOfOrder(serviceBookingQuery.getOrderNumber());
        }
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("a.is_deleted",BusinessConstant.NO)
                .eq("a.is_enabled",BusinessConstant.YES)
                .eq(Objects.nonNull(serviceBookingQuery.getExhibitionManageId()),"a.exhibition_manage_id",serviceBookingQuery.getExhibitionManageId())
                .eq("a.order_number",serviceBookingQuery.getOrderNumber())
                .eq(Objects.nonNull(serviceBookingQuery.getBusinessId()),"a.business_id",serviceBookingQuery.getBusinessId());
        return baseMapper.queryServiceBookingListOfOrder(queryWrapper);
    }

    @Override
    public List<ServiceBookingVO> queryServiceBookingListByOrderNumber(List<String> orderNumber) {
        return baseMapper.queryServiceBookingListByOrderNumber(orderNumber);
    }

    @Override
    public Map<String, List<ServiceBookingVO>> getServiceBookingMapByOrderNumber(List<String> orderNumberList) {
        List<ServiceBookingVO> allServiceBookingList = queryServiceBookingListByOrderNumber(orderNumberList);
        if (allServiceBookingList == null || allServiceBookingList.isEmpty()) {
            return Collections.emptyMap();
        }
        return allServiceBookingList
                .stream()
                .collect(Collectors.groupingBy(ServiceBookingVO::getOrderNumber));
    }

    @Override
    public Boolean updateWorkOrderStatus(String workOrderNo, ServiceBookingWorkOrderStatusEnum statusEnum) {
        return update(new UpdateWrapper<ServiceBooking>().lambda()
                .eq(ServiceBooking::getIsDeleted,BusinessConstant.NO)
                .eq(ServiceBooking::getWorkOrderNo,workOrderNo.split("-")[0])
                .set(ServiceBooking::getWorkOrderStatus,statusEnum));
    }

    @Override
    public List<ServiceBookingVO> queryReportServiceCount(ServiceBookingQuery serviceBookingQuery) {
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("a.is_deleted",BusinessConstant.NO)
                .eq("a.is_enabled",BusinessConstant.YES)
                .notIn("a.order_status",ServiceBookingOrderStatusEnum.CANCEL)
                .eq("d.source_provider",DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode())
                .in("a.declaration_system",Arrays.asList( DataIsolationSystemSceneEnum.P_COMPOSITE_PRODUCER.getCode(),DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode()))
                .eq("a.provider_system", DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode())
                .eq("a.audit_state",ServiceItemAuditStateEnum.APPROVED.getCode())
                .eq("a.exhibition_manage_id ",serviceBookingQuery.getExhibitionManageId())
                .groupBy("a.space_name","a.report_space_status");
        return baseMapper.queryReportServiceCount(queryWrapper);
    }

    @Override
    public List<ServiceBooking> getByReportSpaceNumber(Long reportSpaceId, int isManageOrNot) {
        List<ServiceBooking> list = list(new QueryWrapper<ServiceBooking>().lambda()
                .eq(ServiceBooking::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceBooking::getReportSpaceId, reportSpaceId));
        if(list.isEmpty()){
            return list;
        }
        List<Long> serviceCategoryIds = list.stream().map(ServiceBooking::getServiceCategoryId).collect(Collectors.toList());
        List<ServiceCategory> serviceCategoryList = serviceCategoryService.list(new QueryWrapper<ServiceCategory>()
                .lambda().in(ServiceCategory::getId, serviceCategoryIds).eq(ServiceCategory::getIsManage, isManageOrNot));
        Map<Long, ServiceCategory> serviceCategoryMap = serviceCategoryList.stream().collect(Collectors.toMap(SuperEntity::getId, Function.identity()));
        return list.stream().filter(
                e -> serviceCategoryMap.containsKey(e.getServiceCategoryId())).collect(Collectors.toList());
    }

    @Override
    public void updateOrderNumber(List<ServiceBooking> serviceBookingList, String orderNumber) {
        if(CollectionUtils.isNotEmpty(serviceBookingList)){
            List<Long> idList = serviceBookingList
                    .stream()
                    .map(SuperEntity::getId)
                    .collect(Collectors.toList());
            update(new UpdateWrapper<ServiceBooking>().lambda()
                    .in(ServiceBooking::getId, idList)
                    .set(ServiceBooking::getOrderNumber,orderNumber));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateReportCheckStatus(List<ServiceBookingDTO> list) {
        log.info("updateReportCheckStatus - 更新预定服务的报馆核定状态, list={}", list);
        if (list == null || list.isEmpty()) {
            return false;
        }
        for (int i = 0; i < list.size(); i ++) {
            int rowIndex = i + 2;
            ServiceBookingDTO serviceBookingDTO = list.get(i);
            ServiceBooking serviceBooking = getById(serviceBookingDTO.getId());
            if (serviceBooking == null) {
                throw BizException.wrap(-1, "第" + rowIndex + "行，预定的服务不存在");
            }
            serviceBooking.setReportCheckStatus(serviceBookingDTO.getReportCheckStatus());
            serviceBooking.setSlot(serviceBookingDTO.getSlot());
            updateById(serviceBooking);
        }
        return true;
    }

    @Override
    public List<ServiceBookingSimpleVO> queryExhibitionFinance(Long exhibitionManageId) {
        return baseMapper.queryExhibitionFinance(exhibitionManageId);
    }

    @Override
    public List<ReportVenueSpaceNumVO> queryReportSpaceNum(Long exhibitionManageId) {
        return baseMapper.queryReportSpaceNum(exhibitionManageId);
    }

    @Override
    public List<ServiceBookingSimpleVO> queryWarningRanking() {
        return baseMapper.queryWarningRanking();
    }

    @Override
    public List<ServiceBooking> queryByOrderNumber(String orderNumber) {
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ServiceBooking::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(StringUtils.isNotBlank(orderNumber), ServiceBooking::getOrderNumber, orderNumber)
        ;
        return list(queryWrapper);
    }

    @Override
    public Boolean cancelSettlementServiceItem(Long id) {
        ServiceBooking serviceBooking = getById(id);
        if (Objects.nonNull(serviceBooking)) {
            // 查询订单，判断是否已支付
            ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(serviceBooking.getOrderNumber());
            ServiceBookingPayStateEnum payState = serviceBooking.getPayState();
            if(payState.eq(ServiceBookingPayStateEnum.PAYED)){
                // 已支付状态不可取消
                throw BizException.wrap(VenueServiceExceptionCode.HAS_PAY_STATE_CANT_CANCEL);
            }else {
                // 更新enabled状态
                ServiceBooking updateEntity = new ServiceBooking();
                updateEntity.setId(serviceBooking.getId());
                updateEntity.setIsEnabled(BusinessConstant.NO);
                updateById(updateEntity);
                // 更新订单统计信息
                BigDecimal shouldPayAmount = serviceOrder.getShouldPayAmount();
                ServiceOrder updateServiceOrder = new ServiceOrder();
                updateServiceOrder.setShouldPayAmount(shouldPayAmount.subtract(serviceBooking.getSubtotalPrice()));
                updateServiceOrder.setId(serviceOrder.getId());
                serviceOrderService.updateById(updateServiceOrder);
            }
        }
        return true;
    }

    @Override
    public Boolean updateBookingServiceOrderStatus(ServiceOrder serviceOrder, ServiceBookingDTO serviceBookingDTO) {
        // 处理库存
        ServiceBookingQuery serviceBookingQuery = new ServiceBookingQuery();
        serviceBookingQuery.setOrderNumber(serviceBookingDTO.getOrderNumber());
        List<ServiceBookingVO> serviceBookingVOS = queryServiceBookingListOfOrder(serviceBookingQuery);
        if(CollectionUtils.isNotEmpty(serviceBookingVOS)  &&  Objects.nonNull(serviceOrder) && serviceOrder.getOrderSource().eq(ServiceOrderOrderSourceEnum.SPONSOR_ORDER) ){
            if (serviceBookingDTO.getOrderStatus().equals(ServiceBookingOrderStatusEnum.SUBMIT)) {
                // 提交
                for (ServiceBookingVO serviceBookingVO : serviceBookingVOS) {
                    // 保存出库记录
                    ServiceInventoryOutFlowDTO serviceInventoryOutFlowDTO = new ServiceInventoryOutFlowDTO();
                    serviceInventoryOutFlowDTO.setInventoryCode(serviceBookingVO.getInventoryCode());
                    serviceInventoryOutFlowDTO.setOutNum(BigDecimal.valueOf(serviceBookingVO.getBookingNum()));
                    serviceInventoryOutFlowDTO.setOutStockType(ServiceInventoryOutFlowOutStockTypeEnum.ORDER);
                    serviceInventoryOutFlowDTO.setExhibitionManageId(serviceBookingVO.getExhibitionManageId());
                    serviceInventoryOutFlowService.saveOutFlow(serviceInventoryOutFlowDTO);
                }
            } else if (  serviceBookingDTO.getOrderStatus().equals(ServiceBookingOrderStatusEnum.CANCEL)) {
                // 取消
                for (ServiceBookingVO serviceBookingVO : serviceBookingVOS) {
                    ServiceInventoryInFlowDTO serviceInventoryInFlowDTO = new ServiceInventoryInFlowDTO();
                    serviceInventoryInFlowDTO.setInventoryCode(serviceBookingVO.getInventoryCode());
                    serviceInventoryInFlowDTO.setInNum(BigDecimal.valueOf(serviceBookingVO.getBookingNum()));
                    serviceInventoryInFlowDTO.setInStockType(ServiceInventoryInFlowInStockTypeEnum.ORDER_CANCEL);
                    serviceInventoryInFlowDTO.setExhibitionManageId(serviceBookingVO.getExhibitionManageId());
                    serviceInventoryInFlowDTO.setServiceProviderType(ServiceBorrowReturnGoodsLossStateEnum.UNDAMAGED.getCode());
                    serviceInventoryInFlowService.saveInFlow(serviceInventoryInFlowDTO);
                }
            }
        }
        return update(new UpdateWrapper<ServiceBooking>().lambda().eq(ServiceBooking::getIsDeleted,BusinessConstant.NO)
                .eq(ServiceBooking::getOrderNumber,serviceBookingDTO.getOrderNumber())
                .set(ServiceBooking::getOrderStatus,serviceBookingDTO.getOrderStatus())
                .set(Objects.nonNull(serviceBookingDTO.getAuditState()), ServiceBooking::getAuditState,serviceBookingDTO.getAuditState()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateServiceBookingAuditResult(List<ServiceBookingDTO> serviceBookingList) {
        for (ServiceBookingDTO serviceBookingDTO : serviceBookingList) {
            update(new UpdateWrapper<ServiceBooking>().lambda()
                    .eq(ServiceBooking::getServiceItemId,serviceBookingDTO.getServiceItemId())
                    .eq(ServiceBooking::getReportSpaceId,serviceBookingDTO.getReportSpaceId())
                    .eq(ServiceBooking::getServiceCategoryId,serviceBookingDTO.getServiceCategoryId())
                    .eq(ServiceBooking::getServiceSpecsId,serviceBookingDTO.getServiceSpecsId())
                    .eq(ServiceBooking::getIsDeleted,BusinessConstant.NO)
                    .set(ServiceBooking::getAuditState,serviceBookingDTO.getAuditState())
                    .set(ServiceBooking::getAuditOpinion,serviceBookingDTO.getAuditOpinion())
                    .set(ServiceBooking::getDiscount,serviceBookingDTO.getDiscount())
                    .set(ServiceBooking::getUnitPriceAfterDiscount,serviceBookingDTO.getUnitPriceAfterDiscount())
                    .set(ServiceBooking::getSubtotalServicePrice,serviceBookingDTO.getSubtotalServicePrice())
                    .set(ServiceBooking::getSubtotalPrice,serviceBookingDTO.getSubtotalPrice()));
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ReportServiceAuditDTO>  submitServiceBookingWhenReport(Long reportSpaceId, Long reportSpaceAuditId) {
        // 通过报馆id查询服务预订项
        List<ServiceBookingVO> serviceBookingVOS = queryServiceBookingList(ServiceBookingQuery.builder().reportSpaceId(reportSpaceId).build());
        List<ReportServiceAuditDTO> reportServiceAuditDTOS = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        for (ServiceBookingVO serviceBookingVO : serviceBookingVOS) {
            ReportServiceAuditDTO reportServiceAuditDTO = BeanUtil.copyProperties(serviceBookingVO, ReportServiceAuditDTO.class);
            // 校验最小预定量和库存
            ServiceBookingDTO serviceBookingDTO = BeanUtil.copyProperties(serviceBookingVO, ServiceBookingDTO.class);
            checkServiceBooking(serviceBookingDTO);
            // 更新服务预定项
            update(new UpdateWrapper<ServiceBooking>().lambda()
                    .eq(SuperEntity::getId,serviceBookingVO.getId())
                    .set(ServiceBooking::getAuditState,ReportSpaceAuditServiceAuditStatusEnum.SUBMIT.getCode())
                    .set(ServiceBooking::getAuditOpinion, Strings.EMPTY)
                    .set(ServiceBooking::getBookingTime,now));
            // 审核状态
            reportServiceAuditDTO.setAuditState(ReportSpaceAuditServiceAuditStatusEnum.SUBMIT.getCode());
            // 预订时间
            reportServiceAuditDTO.setBookingTime(now);
            reportServiceAuditDTOS.add(reportServiceAuditDTO);
        }

        return reportServiceAuditDTOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelBookingOfReportSpace(Long reportSpaceId) {
        // 将审核状态还原
        boolean b = update(new UpdateWrapper<ServiceBooking>().lambda()
                .eq(ServiceBooking::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceBooking::getReportSpaceId, reportSpaceId)
                .set(ServiceBooking::getAuditState, null));
        // 删除提交的报馆服务审核记录
        R<Boolean> booleanR = reportServiceAuditFeign.delServiceAuditByReportSpaceId(reportSpaceId);
        if(!booleanR.getIsSuccess()){
            throw new BizException(booleanR.getCode(),booleanR.getMsg());
        }
        return b;
    }

    @Override
    public void exportServiceBookingBySiteName(ServiceBookingDTO serviceBookingDTO, HttpServletResponse response) throws IOException {
        log.info("exportServiceBookingBySiteName - 导出展位预定的展位列表, serviceBookingDTO={}", serviceBookingDTO);
        List<ServiceBookingVO> serviceBookingList = listServiceBookingBySiteName(serviceBookingDTO);
        if (serviceBookingList == null || serviceBookingList.isEmpty()) {
            return;
        }
        List<Map<String, Object>> rows = new ArrayList<>();
        for (ServiceBookingVO serviceBookingVO: serviceBookingList) {
            TreeMap<String, Object> map = new TreeMap<>((o1, o2) -> 1);
            map.put("服务预定编号", serviceBookingVO.getId() + "");
            map.put("服务/商品名称", serviceBookingVO.getServiceName());
            map.put("服务分类", serviceBookingVO.getServiceCategoryName());
            map.put("服务规格", serviceBookingVO.getServiceSpecsName());
            map.put("数量", serviceBookingVO.getBookingNum());
            map.put("槽位", serviceBookingVO.getSlot());
            map.put("核定状态", serviceBookingVO.getReportCheckStatus().getDesc());
            rows.add(map);
        }
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=报馆核定.xlsx");
        try (ServletOutputStream out = response.getOutputStream()) {
            ExcelUtils.export(rows, out);
        }
    }

    @Override
    public List<ServiceBookingDTO> importForReportCheck(MultipartFile file) throws IOException {
        if (file == null) {
            throw BizException.wrap(-1, "未上传文件");
        }
        ExcelReader reader;
        try (InputStream inputStream = file.getInputStream()) {
            reader = ExcelUtil.getReader(inputStream);
        }
        List<Map<String, Object>> importList = reader.readAll();
        if (importList == null || importList.isEmpty()) {
            throw BizException.wrap(-1, "读取数据为空");
        }
        List<ServiceBookingDTO> serviceBookingList = new ArrayList<>();
        for (int i = 0; i < importList.size(); i ++) {
            int rowIndex = i + 2;
            Map<String, Object> map = importList.get(i);
            ServiceBookingDTO serviceBookingDTO = new ServiceBookingDTO();
            Object idObj = map.get("服务预定编号");
            if (ObjectUtils.isEmpty(idObj)) {
                throw BizException.wrap(-1, "第" + rowIndex + "行，服务预定编码为空");
            }
            String idString = (String) idObj;
            serviceBookingDTO.setId(Long.parseLong(idString));
            Object slotObj = map.get("槽位");
            if (ObjectUtils.isNotEmpty(slotObj)) {
                serviceBookingDTO.setSlot((String) slotObj);
            }
            Object reportCheckStatusObj = map.get("核定状态");
            if (ObjectUtils.isEmpty(reportCheckStatusObj)) {
                throw BizException.wrap(-1, "第" + rowIndex + "行，核定状态输入为空");
            }
            String reportCheckString = (String) reportCheckStatusObj;
            if (ServiceBookingReportCheckStatusEnum.HAS_CHECK.getDesc().equals(reportCheckString)) {
                serviceBookingDTO.setReportCheckStatus(ServiceBookingReportCheckStatusEnum.HAS_CHECK);
            } else if (ServiceBookingReportCheckStatusEnum.NOT_CHECK.getDesc().equals(reportCheckString)) {
                serviceBookingDTO.setReportCheckStatus(ServiceBookingReportCheckStatusEnum.NOT_CHECK);
            } else {
                throw BizException.wrap(-1, "第" + rowIndex + "行，核定状态输入非法");
            }
            serviceBookingList.add(serviceBookingDTO);
        }
        return serviceBookingList;
    }

    @Override
    public List<ServiceBookingVO> queryServiceItemAmount(List<Long> ids, Long exhibitionManageId) {
        return baseMapper.queryServiceItemAmount(ids,exhibitionManageId);
    }

    @Override
    public boolean sendVenueReportInnerMsg(Long exhibitionManageId, Long homeId) {
        log.info("sendVenueReportInnerMsg - 主场一键报馆发送站内信, exhibitionManageId={}, homeId={}", exhibitionManageId, homeId);
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(exhibitionManageId);
        if (exhibitionManage == null) {
            log.info("sendVenueReportInnerMsg - 展会缺失，无法发送站内信");
            return false;
        }
        ServiceProvider homeServiceProvider = serviceProviderService.getById(homeId);
        if (homeServiceProvider == null) {
            log.info("sendVenueReportInnerMsg - 主场缺失，无法发送站内信");
            return false;
        }
        String content = String.format(BusinessInnerMsgTemplate.REPORT_VENUE_TEMPLATE, exhibitionManage.getExhibitionName(), homeServiceProvider.getCompanyName());
        sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
        return true;
    }

    @Override
    public void asyncSendVenueReportInnerMsg(Long exhibitionManageId, Long homeId) {
        threadPoolTaskExecutor.execute(() -> sendVenueReportInnerMsg(exhibitionManageId, homeId));
    }

    @Override
    public List<Map<String, Object>> countHomeServiceBookingNum(Long exhibitionManageId, Long homeId, Integer topN) {
        log.info("countHomeServiceBookingNum - 统计服务预定排行, exhibitionManageId={}, homeId={}, topN={}", exhibitionManageId, homeId, topN);
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("so.is_deleted", BusinessConstant.DELETE_NO)
                .eq(exhibitionManageId != null, "so.exhibition_manage_id", exhibitionManageId)
                .in("so.belong_system", MenuAffiliationEnum.P_COMPOSITE_COURT.getCode(), MenuAffiliationEnum.P_COMPOSITE_PRODUCER.getCode())
                .ne("so.order_status", ServiceBookingOrderStatusEnum.CANCEL.getCode())
                .groupBy("si.id")
                .orderByDesc("sum(sb.booking_num)")
                .last(topN != null, "limit " + topN)
        ;

        List<ServiceBookingVO> serviceBookingList = baseMapper.countHomeServiceBookingNum(queryWrapper);
        if (serviceBookingList == null || serviceBookingList.isEmpty()) {
            return Collections.emptyList();
        }
        List<Map<String, Object>> list = serviceBookingList
                .stream()
                .map(serviceBookingVO -> {
                    Map<String, Object> map = new HashMap<>(16);
                    map.put("name", serviceBookingVO.getServiceName());
                    map.put("value", serviceBookingVO.getBookingNum());
                    return map;
                })
                .collect(Collectors.toList());
        return list;
    }

    @Override
    public List<Map<String, Object>> countHomeHasPayServiceBookingNum(Long exhibitionManageId, Long homeId, Integer topN) {
        log.info("countHomeHasPayServiceBookingNum - 统计服务已销售排行, exhibitionManageId={}, homeId={}, topN={}", exhibitionManageId, homeId, topN);
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("so.is_deleted", BusinessConstant.DELETE_NO)
                .eq(exhibitionManageId != null, "so.exhibition_manage_id", exhibitionManageId)
                .in("so.belong_system", MenuAffiliationEnum.P_COMPOSITE_COURT.getCode(), MenuAffiliationEnum.P_COMPOSITE_PRODUCER.getCode())
                .ne("so.order_status", ServiceBookingOrderStatusEnum.CANCEL.getCode())
                .eq("so.pay_status", ServiceOrderPayStatusEnum.HAS_PAY.getCode())
                .groupBy("si.id")
                .orderByDesc("sum(sb.booking_num)")
                .last(topN != null, "limit " + topN)
        ;
        List<ServiceBookingVO> serviceBookingList = baseMapper.countHomeServiceBookingNum(queryWrapper);
        if (serviceBookingList == null || serviceBookingList.isEmpty()) {
            return Collections.emptyList();
        }
        List<Map<String, Object>> list = serviceBookingList
                .stream()
                .map(serviceBookingVO -> {
                    Map<String, Object> map = new HashMap<>(16);
                    map.put("name", serviceBookingVO.getServiceName());
                    map.put("value", serviceBookingVO.getBookingNum());
                    return map;
                })
                .collect(Collectors.toList());
        return list;
    }

    @Override
    public List<ServiceBookingVO> countReportServiceProcess(ServiceBookingQuery serviceBookingQuery) {
        log.info("countReportServiceProcess - 统计展会报馆进度, serviceBookingQuery={}", serviceBookingQuery);
        List<ServiceBookingVO> serviceBookingList = queryReportServiceCount(serviceBookingQuery);
        if (serviceBookingList == null || serviceBookingList.isEmpty()) {
            return Collections.emptyList();
        }
        Map<String, List<ServiceBookingVO>> serviceBookingMap = serviceBookingList
                .stream()
                .filter(serviceBookingVO -> StrUtil.isNotBlank(serviceBookingVO.getSpaceName()))
                .collect(Collectors.groupingBy(ServiceBookingVO::getSpaceName));
        List<ServiceBookingVO> list = new ArrayList<>();
        for (Map.Entry<String, List<ServiceBookingVO>> map: serviceBookingMap.entrySet()) {
            ServiceBookingVO serviceBookingVO = new ServiceBookingVO();
            String spaceName = map.getKey();
            serviceBookingVO.setSpaceName(spaceName);
            List<ServiceBookingVO> spaceServiceBookingList = map.getValue();
            if (spaceServiceBookingList == null || spaceServiceBookingList.isEmpty()) {
                serviceBookingVO.setReportVenueProcess("0");
                list.add(serviceBookingVO);
                continue;
            }
            long hasReportNum = 0L;
            long notReportNum = 0L;
            long totalServiceNum;
            for (ServiceBookingVO queryServiceBooking : spaceServiceBookingList) {
                if (ServiceBookingReportSpaceStatusEnum.REPORTED.getCode().equals(queryServiceBooking.getReportSpaceStatus().getCode())) {
                    hasReportNum = queryServiceBooking.getBookingNum() == null ? 0L : queryServiceBooking.getBookingNum();
                } else if (ServiceBookingReportSpaceStatusEnum.NOT_REPORTED.getCode().equals(queryServiceBooking.getReportSpaceStatus().getCode())) {
                     notReportNum = queryServiceBooking.getBookingNum() == null ? 0L : queryServiceBooking.getBookingNum();
                }
            }
            totalServiceNum = hasReportNum + notReportNum;
            if (totalServiceNum == 0L || hasReportNum == 0L) {
                serviceBookingVO.setReportVenueProcess("0");
                list.add(serviceBookingVO);
                continue;
            }
            BigDecimal percent = BigDecimal.valueOf(hasReportNum)
                    .divide(BigDecimal.valueOf(totalServiceNum), 2, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100L))
                    ;
            serviceBookingVO.setReportVenueProcess(percent.doubleValue() + "%");
            list.add(serviceBookingVO);
        }
        return list
                .stream()
                .sorted((o1, o2) -> StrUtil.compare(o2.getReportVenueProcess(), o1.getReportVenueProcess(), false))
                .collect(Collectors.toList());
    }

    @Override
    public Boolean submitServiceBookingToDispatch(List<ServiceBookingDTO> serviceBookingDTO) {
        for (ServiceBookingDTO bookingDTO : serviceBookingDTO) {
            ServiceBooking serviceBooking = new ServiceBooking();
            serviceBooking.setId(bookingDTO.getId());
            serviceBooking.setWorkOrderStatus(ServiceBookingWorkOrderStatusEnum.HAS_DISPATCH);
            updateById(serviceBooking);
            // 更新服务订单状态
            updateServiceOrderStatus(bookingDTO);
        }
        return true;
    }

    /**
     * 更新服务订单状态
     * @param bookingDTO bookingDTO
     */
    private void updateServiceOrderStatus(ServiceBookingDTO bookingDTO) {
        ServiceBooking booking = getById(bookingDTO.getId());
        String orderNumber = booking.getOrderNumber();
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        ServiceOrderPayStatusEnum payStatus = serviceOrder.getPayStatus();
        if(ServiceOrderPayStatusEnum.HAS_PAY.eq(payStatus)){
            // 如果已经是支付状态，那么订单状态修改为已完成
            ServiceOrderDTO serviceOrderDTO = new ServiceOrderDTO();
            serviceOrderDTO.setId(serviceOrder.getId());
            serviceOrderDTO.setOrderNumber(orderNumber);
            serviceOrderDTO.setWorkOrderStatus(ServiceOrderWorkOrderStatusEnum.HAS_DISPATCH);
            serviceOrderDTO.setOrderStatus(ServiceOrderOrderStatusEnum.COMPLETE);
            serviceOrderService.updateServiceOrder(serviceOrderDTO);
        }else {
            // 如果已经是未支付状态，那么订单状态修改为已派单
            ServiceOrderDTO serviceOrderDTO = new ServiceOrderDTO();
            serviceOrderDTO.setId(serviceOrder.getId());
            serviceOrderDTO.setOrderNumber(orderNumber);
            serviceOrderDTO.setWorkOrderStatus(ServiceOrderWorkOrderStatusEnum.HAS_DISPATCH);
            serviceOrderDTO.setOrderStatus(ServiceOrderOrderStatusEnum.DISPATCH);
            serviceOrderService.updateServiceOrder(serviceOrderDTO);
        }
    }

    @Override
    public Boolean updateServiceInventory(ServiceOrderDTO serviceOrderDTO) {
        // 处理库存
        ServiceBookingQuery serviceBookingQuery = new ServiceBookingQuery();
        serviceBookingQuery.setOrderNumber(serviceOrderDTO.getOrderNumber());
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(serviceOrderDTO.getOrderNumber());
        List<ServiceBookingVO> serviceBookingVOS = queryServiceBookingListOfOrder(serviceBookingQuery);
        if (Objects.nonNull(serviceOrderDTO.getPayStatus()) && serviceOrderDTO.getPayStatus().equals(ServiceOrderPayStatusEnum.HAS_PAY) && !serviceOrder.getOrderStatus().eq(ServiceOrderOrderStatusEnum.CANCEL)) {
            // 提交
            for (ServiceBookingVO serviceBookingVO : serviceBookingVOS) {
                // 保存出库记录
                ServiceInventoryOutFlowDTO serviceInventoryOutFlowDTO = new ServiceInventoryOutFlowDTO();
                serviceInventoryOutFlowDTO.setInventoryCode(serviceBookingVO.getInventoryCode());
                serviceInventoryOutFlowDTO.setOutNum(BigDecimal.valueOf(serviceBookingVO.getBookingNum()));
                serviceInventoryOutFlowDTO.setOutStockType(ServiceInventoryOutFlowOutStockTypeEnum.ORDER);
                serviceInventoryOutFlowDTO.setExhibitionManageId(serviceBookingVO.getExhibitionManageId());
                serviceInventoryOutFlowService.saveOutFlow(serviceInventoryOutFlowDTO);
            }
        } else if (Objects.nonNull(serviceOrderDTO.getOrderStatus()) && serviceOrderDTO.getOrderStatus().eq(ServiceOrderOrderStatusEnum.CANCEL) && serviceOrder.getPayStatus().equals(ServiceOrderPayStatusEnum.HAS_PAY)) {
            // 取消
            for (ServiceBookingVO serviceBookingVO : serviceBookingVOS) {
                ServiceInventoryInFlowDTO serviceInventoryInFlowDTO = new ServiceInventoryInFlowDTO();
                serviceInventoryInFlowDTO.setInventoryCode(serviceBookingVO.getInventoryCode());
                serviceInventoryInFlowDTO.setInNum(BigDecimal.valueOf(serviceBookingVO.getBookingNum()));
                serviceInventoryInFlowDTO.setInStockType(ServiceInventoryInFlowInStockTypeEnum.ORDER_CANCEL);
                serviceInventoryInFlowDTO.setExhibitionManageId(serviceBookingVO.getExhibitionManageId());
                serviceInventoryInFlowDTO.setServiceProviderType(ServiceBorrowReturnGoodsLossStateEnum.UNDAMAGED.getCode());
                serviceInventoryInFlowService.saveInFlow(serviceInventoryInFlowDTO);
            }
        }
        return true;
    }

    @Override
    public ServiceBookingStatisticsVO querySponsorServiceBookingStat(ServiceBookingQuery serviceBookingQuery) {
        QueryWrapper<ServiceBooking> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("a.is_deleted", BusinessConstant.DELETE_NO)
                .notIn("a.order_status",Arrays.asList(ServiceBookingOrderStatusEnum.NOT_SUBMIT,ServiceBookingOrderStatusEnum.CANCEL) )
                .in("a.exhibition_manage_id",serviceBookingQuery.getExhibitionManageId() )
                .eq("a.business_id",serviceBookingQuery.getBusinessId() )
                .groupBy("a.service_item_id,a.service_specs_id");
        List<ServiceBookingVO> serviceBooking = baseMapper.querySponsorServiceBookingStat(queryWrapper);
        ServiceBookingStatisticsVO serviceBookingStatisticsVO = new ServiceBookingStatisticsVO();
        serviceBookingStatisticsVO.setServiceBookingVO(serviceBooking);
        serviceBookingStatisticsVO.setTotalPrice(serviceBooking.stream().map(ServiceBookingVO::getSubtotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add));
        return serviceBookingStatisticsVO;
    }

    /**
     * 校验预订数量
     * @param reportServiceAuditDTO reportServiceAuditDTO
     */
    private void checkBookingNum(ReportServiceAuditDTO reportServiceAuditDTO) {
        Long bookingNum = reportServiceAuditDTO.getBookingNum();
        Long inventoryNum = reportServiceAuditDTO.getInventoryNum();
        Long minBookNum = reportServiceAuditDTO.getMinBookNum();
        if(Objects.nonNull(bookingNum) && bookingNum!=0 ){
            // 不允许预订量小于最小预定量限制
            if (Objects.nonNull(minBookNum) && bookingNum < minBookNum) {
                throw BizException.wrap(VenueServiceExceptionCode.NUM_CANT_LESS_TRAN_MIN);
            }
            // 不允许服务预定量大于当前库存量
            if (Objects.isNull(inventoryNum) || bookingNum > inventoryNum) {
                throw BizException.wrap(VenueServiceExceptionCode.NUM_CANT_MORE_TRAN_INVENTORY);
            }
        }
    }
}
